﻿using RaytracerLib.MathLib;
using RaytracerLib.Layers.Interpolators;
using RaytracerLib.Layers.OverlayCorrectors;

namespace RaytracerLib.Layers
{
    public static class LayersFactory
    {
        public static Layer Solid(ColorFloat a_color)
        {
            return new SolidColorLayer(a_color);
        }

        public static Layer Solid(double a_value)
        {
            return new SolidValueLayer(a_value);
        }

        public static Layer TextureFromFile(string a_fileName,
            InterpolationMethod a_interpolationMethod,
            OverlayMethod a_overlayMethod)
        {
            return new ColorArrayFloatFile(a_fileName, a_overlayMethod: a_overlayMethod, 
                a_interpolationMethod: a_interpolationMethod);
        }

        public static Layer ValuesFromFile(string a_fileName,
            InterpolationMethod a_interpolationMethod,
            OverlayMethod a_overlayMethod)
        {
            return new ValueArrayFloatFile(a_fileName, a_overlayMethod,
                a_interpolationMethod);
        }

        public static Layer TangentsFromFile(string a_fileName,
            InterpolationMethod a_interpolationMethod,
            OverlayMethod a_overlayMethod)
        {
            return new ValueArrayFloatFile(a_fileName, a_overlayMethod,
                a_interpolationMethod);
        }

        public static Layer Procedural(string a_source)
        {
            return new ProceduralLayer(a_source);
        }

        public static Layer Transparent(Layer a_topLayer, Layer a_bottomLayer, double a_alpha)
        {
            return Transparent(a_topLayer, a_bottomLayer, Solid(a_alpha));
        }

        public static Layer Transparent(Layer a_top, Layer a_bottom, Layer a_alpha)
        {
            return new TransparentOperationLayer(a_top, a_bottom, a_alpha);
        }

        public static Layer Scale(Layer a_childLayer, Vector2 a_ratio)
        {
            return new ScaleOperationLayer(a_childLayer, a_ratio);
        }

        public static Layer Offset(Layer a_childLayer, Vector2 a_offset)
        {
            return new OffsetOperationLayer(a_offset, a_childLayer);
        }

        public static Layer Neg(Layer a_childLayer)
        {
            return new NegOperationLayer(a_childLayer);
        }

        public static Layer Mul(Layer a_childLayer1, Layer a_childLayer2)
        {
            return new MulOperationLayer(a_childLayer1, a_childLayer2);
        }

        public static Layer Mul(Layer a_childLayer, double a_ratio)
        {
            return Mul(a_childLayer, Solid(a_ratio));
        }

        public static Layer Mul(Layer a_childLayer, ColorFloat a_ratio)
        {
            return Mul(a_childLayer, Solid(a_ratio));
        }

        public static Layer Threshold(Layer a_childLayer, ColorFloat a_level)
        {
            return new ThresholdColorOperationLayer(a_childLayer, a_level);
        }

        public static Layer Threshold(Layer a_childLayer, double a_level)
        {
            return new ThresholdValueOperationLayer(a_childLayer, a_level);
        }

        public static Layer Sub(Layer a_childLayer1, Layer a_childLayer2)
        {
            return new SubOperationLayer(a_childLayer1, a_childLayer2);
        }

        public static Layer Sub(ColorFloat a_sub, Layer a_childLayer2)
        {
            return Sub(Solid(a_sub), a_childLayer2);
        }

        public static Layer Sub(double a_sub, Layer a_childLayer2)
        {
            return Sub(Solid(a_sub), a_childLayer2);
        }

        public static Layer Add(Layer a_childLayer1, Layer a_childLayer2)
        {
            return new AddOperationLayer(a_childLayer1, a_childLayer2);
        }

        public static Layer Add(Layer a_childLayer1, double a_value)
        {
            return Add(a_childLayer1, Solid(a_value));
        }

        public static Layer Add(Layer a_childLayer1, ColorFloat a_value)
        {
            return Add(a_childLayer1, Solid(a_value));
        }

        public static Layer Div(Layer a_childLayer1, Layer a_childLayer2)
        {
            return new DivOperationLayer(a_childLayer1, a_childLayer2);
        }

        public static Layer Div(Layer a_childLayer, ColorFloat a_dividor)
        {
            return Div(a_childLayer, Solid(a_dividor));
        }

        public static Layer Div(Layer a_childLayer, double a_dividor)
        {
            return Div(a_childLayer, Solid(a_dividor));
        }

        public static Layer Div(ColorFloat a_divisor, Layer a_childLayer)
        {
            return Div(Solid(a_divisor), a_childLayer);
        }

        public static Layer Div(double a_divisor, Layer a_childLayer)
        {
            return Div(Solid(a_divisor), a_childLayer);
        }

        public static Layer Transform(Layer a_childLayer, Matrix3 a_transform)
        {
            return new TransformOperationLayer(a_childLayer, a_transform);
        }
    }
}